<?php
namespace App\Services\AppletUser;

use App\Facades\EasyWechat;

/**
 * 微信用户相关服务类
 * @package App\Services
 */
class UserService extends \App\Services\WxCommon\WxBase
{
    /**
     * 构造函数
     * @param string $appid
     * @throws \Exception
     */
    public function __construct($appid = '')
    {
        parent::__construct($appid);
        $this->app = EasyWechat::miniProgram($this->appid);
    }

    /**
     * 通过临时登录凭证code生成用户token
     * @param $code
     * @throws \EasyWeChat\Kernel\Exceptions\InvalidConfigException
     */
    public function code2Session($code)
    {
        $sessionData = $this->app->auth->session($code);
        if (isset($sessionData['errcode']) && $sessionData['errcode'] != 0) {
            throw new \Exception($sessionData['errmsg']);
        }
        if (empty($sessionData['openid'])){
            throw new \Exception('获取用户数据失败');
        }
        $cacheData = [
            'openid' => $sessionData['openid'] ?? '',
            'unionid' => $sessionData['unionid'] ?? '',
            'session_key' => $sessionData['session_key'] ?? '',
        ];

        //写入用户数据
        $wxUser = \App\Models\WxUser::firstOrCreate(
            ['appid'=>$this->appid,'openid'=>$cacheData['openid']],
            ['unionid'=>$cacheData['unionid']]
        );
        if ($wxUser){
            $cacheData['userInfo'] = $wxUser->toArray();
        }
        //保存到缓存
        $token = $this->appid . '_' . $cacheData['openid'] . '_' . microtime(true);
        $token = md5($token);
        $expiresAt = now()->addHours(2);
        \Cache::put($token, $cacheData, $expiresAt);
        return $token;
    }

    /**
     * 通过用户token获取用户数据
     * @param $token
     * @return mixed
     */
    public function getUserByToken($token)
    {
        return \Cache::get($token);
    }

    /**
     * 解密用户数据
     * @param $token
     * @param $iv
     * @param $encryptData
     * @return array
     * @throws \EasyWeChat\Kernel\Exceptions\DecryptException
     */
    public function decryptData($token, $iv, $encryptData)
    {
        $userData = $this->getUserByToken($token);
        $decryptedData = $this->app->encryptor->decryptData($userData['session_key'], $iv, $encryptData);
        return $decryptedData;
    }

    /**
     * 解密用户数据
     * @param $token
     * @param $iv
     * @param $encryptData
     */
    public function decryptUserData($token, $iv, $encryptData){
        $userData = $this->getUserByToken($token);
        $decryptedData = $this->app->encryptor->decryptData($userData['session_key'], $iv, $encryptData);
        if(empty($decryptedData)){
            throw new \Exception('用户数据解密失败');
        }
        $upUserData = [
            'nickname'=>$decryptedData['nickName'] ?? '',
            'sex'=>$decryptedData['gender'] ?? '',
            'headimgurl'=>$decryptedData['avatarUrl'] ?? '',
            'language'=>$decryptedData['language'] ?? '',
            'country'=>$decryptedData['country'] ?? '',
            'province'=>$decryptedData['province'] ?? '',
            'city'=>$decryptedData['city'] ?? '',
        ];
        //写入用户数据
        \App\Models\WxUser::updateOrCreate(['openid'=>$userData['openid'], 'appid'=>$this->appid,], $upUserData);
        //解密出来的用户数据保存至缓存中;
        if (!empty($userData['userInfo'])){
            $userData['userInfo'] = array_merge($userData['userInfo'], $upUserData);
        }else{
            $userData['userInfo'] = $upUserData;
        }
        $expiresAt = now()->addHours(2);
        \Cache::put($token, $userData, $expiresAt);
        return $userData;
    }

    /**
     * 解密用户手机数据
     * @param $token
     * @param $iv
     * @param $encryptData
     * @return mixed
     * @throws \EasyWeChat\Kernel\Exceptions\DecryptException
     */
    public function decryptPhoneData($token, $iv, $encryptData){
        $userData = $this->getUserByToken($token);
        $decryptedData = $this->app->encryptor->decryptData($userData['session_key'], $iv, $encryptData);
        if(empty($decryptedData)){
            throw new \Exception('用户手机数据解密失败');
        }
        $phoneData = [
            'phone'=>$decryptedData['phoneNumber'] ?? '',
            'pure_phone'=>$decryptedData['purePhoneNumber'] ?? '',
            'country_code'=>$decryptedData['countryCode'] ?? '',
        ];
        //写入用户数据
        \App\Models\WxUser::updateOrCreate(['appid'=>$this->appid,'openid'=>$userData['openid']], $phoneData);
        //解密出来的用户数据保存至缓存中
        if (!empty($userData['userInfo'])){
            $userData['userInfo'] = array_merge($userData['userInfo'], $phoneData);
        }else{
            $userData['userInfo'] = $phoneData;
        }
        $expiresAt = now()->addHours(2);
        \Cache::put($token, $userData, $expiresAt);
        return $userData;
    }

    /**
     * 通过openid获取用户数据
     * @param $openid
     * @return mixed
     */
    public function getUserByOpenId($openid)
    {
        return \App\Models\WxUser::where('openid', $openid)->first();
    }
}